home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / Amiga_Mail_Vol2 / Archives / Plain / nd90 / Dr2D / DR2D.txt < prev    next >
Encoding:
Text File  |  1991-01-16  |  34.4 KB  |  952 lines

  1. (c)  Copyright 1991 Commodore-Amiga, Inc.   All rights reserved.
  2. The information contained herein is subject to change without notice,
  3. and is provided "as is" without warranty of any kind, either expressed
  4. or implied.  The entire risk as to the use of this information is
  5. assumed by the user.
  6.  
  7.  
  8.  
  9. The DR2D FORM
  10.  
  11.  
  12.  
  13. by Ross Cunniff and John Orr
  14.  
  15.  
  16. A standard IFF FORM to describe 2D drawings has been sorely needed for
  17. a long time.  Several commercial drawing packages have been available
  18. for some time but none has established its file format as the Amiga
  19. standard.  The absence of a 2D drawing standard hinders the
  20. development of applications that use 2D drawings as it forces each
  21. application to understand several private standards instead of a
  22. single one.  Without a standard, data exchange for both the developer
  23. and the user is difficult, if not impossible.
  24.  
  25. The DR2D FORM fills this void.  This FORM was developed by Taliesin,
  26. Inc. for use as the native file format for their two-dimensional
  27. structured drawing package, ProVector.  Saxon Industries and Soft
  28. Logik Publishing Corporation are planning to support this new FORM in
  29. the near future.
  30.  
  31. Many of the values stored in the DR2D FORM are stored as IEEE single
  32. precision floating point numbers.  These numbers consist of 32 bits,
  33. arranged as follows:
  34.  
  35.  _______________________________________________________________________
  36. | s e e e e e e e | e m m m m m m m | m m m m m m m m | m m m m m m m m |
  37.  -----------------------------------------------------------------------
  38.   31            24  23            16  15            8   7             0
  39.  
  40.  
  41. where: 
  42.  
  43.     s    is the sign of the number where 1 is negative and 0 is
  44.           positive. 
  45.     e    is the 8 bit exponent in excess 127 form.  This number
  46.           is the power of two to which the mantissa is raised
  47.           (Excess 127 form means that 127 is added to the
  48.           exponent before packing it into the IEEE number.) 
  49.     m    is the 23 bit mantissa.  It ranges from 1.0000000 to
  50.           1.999999..., where the leading base-ten one is
  51.           assumed. 
  52.  
  53. An IEEE single precision with the value of 0.0000000 has all its bits
  54. cleared. 
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64. The DR2D Chunks
  65.  
  66.  
  67. FORM (0x464F524D)      /* All drawings are a FORM */
  68.  
  69.     struct FORMstruct {
  70.         ULONG    ID;            /* DR2D */
  71.         ULONG    Size;
  72.     };
  73.  
  74.  
  75. DR2D (0x44523244)  /* ID of 2D drawing */
  76.  
  77.  
  78. The DR2D chunks are broken up into three groups: the global drawing
  79. attribute chunks, the object attribute chunks, and the object chunks.
  80. The global drawing attribute chunks describe elements of a 2D drawing
  81. that are common to many objects in the drawing.  Document preferences,
  82. palette information, and custom fill patterns are typical
  83. document-wide settings defined in global drawing attribute chunks.
  84. The object attribute chunks are used to set certain properties of the
  85. object chunk(s) that follows the object attribute chunk.  The current
  86. fill pattern, dash pattern, and line color are all set using an object
  87. attribute chunk.  Object chunks describe the actual DR2D drawing.
  88. Polygons, text, and bitmaps are found in these chunks.
  89.  
  90.  
  91.  
  92. The Global Drawing Attribute Chunks
  93.  
  94. The following chunks describe global attributes of a DR2D document.
  95.  
  96. DRHD (0x44524844)     /* Drawing header */
  97.  
  98. The DRHD chunk contains the upper left and lower right extremes of the
  99. document in (X, Y) coordinates.  This chunk is required and should
  100. only appear once in a document in the outermost layer of the DR2D file
  101. (DR2Ds can be nested).
  102.  
  103.     struct DRHDstruct {
  104.         ULONG    ID;
  105.         ULONG    Size;            /* Always 16 */
  106.         IEEE    XLeft, YTop,
  107.             XRight, YBot;
  108.     };
  109.  
  110.  
  111. The point (XLeft,YTop) is the upper left corner of the project and the
  112. point (XRight,YBot) is its lower right corner.  These coordinates not
  113. only supply the size and position of the document in a coordinate
  114. system, they also supply the project's orientation.  If XLeft <
  115. XRight, the X-axis increases toward the right.  If YTop < YBot, the
  116. Y-axis increases toward the bottom.  Other combinations are possible;
  117. for example in Cartesian coordinates, XLeft would be less than XRight
  118. but YTop would be greater than YBot.
  119.  
  120.  
  121.  
  122.  
  123.  
  124. PPRF (0x50505249)       /* Page preferences */
  125.  
  126. The PPRF chunk contains preference settings for ProVector.  Although
  127. this chunk is not required, its use is encouraged because it contains
  128. some important environment information.
  129.  
  130.     struct PPRFstruct {
  131.         ULONG    ID;
  132.         ULONG    Size;
  133.         char    Prefs[Size];
  134.     };
  135.  
  136. DR2D stores preferences as a concatenation of several null-terminated
  137. strings, in the Prefs[] array.  The strings can appear in any order.
  138. The currently supported strings are:
  139.  
  140.         Units=<unit-type>
  141.         Portrait=<boolean>
  142.         PageType=<page-type>
  143.         GridSize=<number>
  144.  
  145. where:
  146.         <unit-type>     is either Inch, Cm, or Pica
  147.         <boolean>       is either True or False
  148.         <page-type>     is either Standard, Legal, B4, B5, A3,
  149.                   A4, A5, or Custom 
  150.         <number>        is a floating-point number
  151.  
  152. The DR2D FORM does not require this chunk to explicitly state all the
  153. possible preferences.  In the absence of any particular preference
  154. string, a DR2D reader should fall back on the default value.  The
  155. defaults are:
  156.  
  157.         Units=Inch
  158.         Portrait=True
  159.         PageType=Standard
  160.         GridSize=1.0
  161.  
  162.  
  163. CMAP (0x434D4150)       /* Color map (Same as ILBM CMAP) */
  164.  
  165. This chunk is identical to the ILBM CMAP chunk as described in the IFF
  166. ILBM documentation.
  167.  
  168.     struct CMAPstruct {
  169.         ULONG    ID;
  170.         ULONG    Size;
  171.         UBYTE    ColorMap[Size];
  172.     };
  173.  
  174. ColorMap is an array of 24-bit RGB color values.  The 24-bit value is
  175. spread across three bytes, the first of which contains the red
  176. intensity, the next contains the green intensity, and the third
  177. contains the blue intensity.  Because DR2D stores its colors with
  178. 24-bit accuracy, DR2D readers must not make the mistake that some ILBM
  179. readers do in assuming the CMAP chunk colors correspond directly to
  180. Amiga color registers.
  181.  
  182.  
  183.  
  184. FONS (0x464F4E53)       /* Font chunk (Same as FTXT FONS chunk) */
  185.  
  186. The FONS chunk contains information about a font used in the DR2D
  187. FORM.  ProVector does not include support for Amiga fonts.  Instead,
  188. ProVector uses fonts defined in the OFNT FORM which is documented
  189. later in this article.
  190.  
  191.     struct FONSstruct {
  192.         ULONG    ID;
  193.         ULONG    Size;
  194.         UBYTE    FontID;        /* ID the font is referenced by */
  195.         UBYTE    Pad1;              /* Always 0 */
  196.         UBYTE    Proportional;    /* Is it proportional? */
  197.         UBYTE    Serif;        /* does it have serifs? */
  198.         CHAR    Name[Size-4];    /* The name of the font */
  199.     };
  200.  
  201. The UBYTE FontID field is the number DR2D assigns to this font.
  202. References to this font by other DR2D chunks are made using this
  203. number.    
  204.  
  205. The Proportional and Serif fields indicate properties of this font.
  206. Specifically, Proportional indicates if this font is proportional, and
  207. Serif indicates if this font has serifs.  These two options were
  208. created to allow for font substitution in case the specified font is
  209. not available.  They are set according to these values:
  210.  
  211.     0    The DR2D writer didn't know if this font is
  212.           proportional/has serifs. 
  213.     1    No, this font is not proportional/does not have
  214.           serifs. 
  215.     2    Yes, this font is proportional/does have serifs.
  216.  
  217. The last field, Name[], is a NULL terminated string containing the
  218. name of the font. 
  219.  
  220.  
  221. DASH (0x44415348)       /* Line dash pattern for edges */
  222.  
  223. This chunk describes the on-off dash pattern associated with a line.
  224.  
  225.     struct DASHstruct {
  226.         ULONG    ID;
  227.         ULONG    Size;
  228.         USHORT    DashID;            /* ID of the dash pattern */
  229.         USHORT    NumDashes;         /* Should always be even */
  230.         IEEE    Dashes[NumDashes];      /* On-off pattern */
  231.     };
  232.  
  233. DashID is the number assigned to this specific dash pattern.
  234. References to this dash pattern by other DR2D chunks are made using
  235. this number.
  236.  
  237. The Dashes[] array contains the actual dash pattern.  The first number
  238. in the array (element 0) is the length of the ``on'' portion of the
  239. pattern.  The second number (element 1) specifies the ``off'' portion
  240. of the pattern.  If there are more entries in the Dashes array, the
  241. pattern will continue.  Even-index elements specify the length of an
  242. ``on'' span, while odd-index elements specify the length of an ``off''
  243. span.  There must be an even number of entries.  These lengths are not
  244. in the same units as specified in the PPRF chunk, but are multiples of
  245. the line width, so a line of width 2.5 and a dash pattern of 1.0, 2.0
  246. would have an ``on'' span of length 1.0 x 2.5 = 2.5 followed by an
  247. ``off'' span of length 2.0 x 2.5 = 5.  The following figure shows
  248. several dash pattern examples.  Notice that for lines longer than the
  249. dash pattern, the pattern repeats.
  250.  
  251.  
  252. [figure 1 - dash patterns]
  253.  
  254. By convention, DashID 0 is reserved to mean `No line pattern at all',
  255. i.e. the edges are invisible.  This DASH pattern should not be defined
  256. by a DR2D DASH chunk.  Again by convention, a NumDashes of 0 means
  257. that the line is solid.
  258.  
  259.  
  260. AROW (0x41524F57)       /* An arrow-head pattern */
  261.  
  262. The AROW chunk describes an arrowhead pattern.  DR2D open polygons
  263. (OPLY) can have arrowheads attached to their endpoints.  See the
  264. description of the OPLY chunk later in this article for more
  265. information on the OPLY chunk.
  266.  
  267.  
  268.     #define ARROW_FIRST  0x01 /* Draw an arrow on the OPLY's first point */
  269.     #define ARROW_LAST   0x02 /* Draw an arrow on the OPLY's last point */
  270.  
  271.     struct AROWstruct {
  272.         ULONG    ID;
  273.         ULONG    Size;
  274.         UBYTE    Flags;        /* Flags, from ARROW_*, above */
  275.         UBYTE    Pad0;        /* Should always 0 */
  276.         USHORT    ArrowID;    /* Name of the arrow head */
  277.         USHORT    NumPoints;
  278.         IEEE    ArrowPoints[NumPoints*2];
  279.     };
  280.  
  281.  
  282. The Flags field specifies which end(s) of an OPLY to place an
  283. arrowhead based on the #defines above.  ArrowID is the number by which
  284. an OPLY will reference this arrowhead pattern.
  285.  
  286. The coordinates in the array ArrowPoints[] define the arrowhead's
  287. shape.  These points form a closed polygon.  See the section on the
  288. OPLY/CPLY object chunks for a descriptionof how DR2D defines shapes.
  289. The arrowhead is drawn in the same coordinate system relative to the
  290. endpoint of the OPLY the arrowhead is attached to.  The arrowhead's
  291. origin (0,0) coincides with the OPLY's endpoint.  DR2D assumes that
  292. the arrowhead represented in the AROW chunk is pointing to the right
  293. so the proper rotation can be applied to the arrowhead.  The arrow is
  294. filled according to the current fill pattern set in the ATTR object
  295. attribute chunk.
  296.  
  297.  
  298.  
  299. FILL (0x46494C4C)       /* Object-oriented fill pattern */
  300.  
  301. The FILL chunk defines a fill pattern.  This chunk is only valid
  302. inside nested DR2D FORMs.  The GRUP object chunk section of this
  303. article contans an example of the FILL chunk.
  304.  
  305.     struct FILLstruct {
  306.         ULONG    ID;
  307.         ULONG    Size;
  308.         USHORT    FillID;          /* ID of the fill */
  309.     };
  310.  
  311. FillID is the number by which the ATTR object attribute chunk
  312. references fill patterns.  The FILL chunk must be the first chunk
  313. inside a nested DR2D FORM.  A FILL is followed by one DR2D object plus
  314. any of the object attribute chunks (ATTR, BBOX) associated with the
  315. object.
  316.  
  317. [Figure 2 - fill patterns]
  318.  
  319.  
  320. DR2D makes a ``tile'' out of the fill pattern, giving it a virtual
  321. bounding box based on the extreme X and Y values of the FILL's object
  322. (Fig. A).  The bounding box shown in Fig. A surrounding the pattern
  323. (the two ellipses) is invisible to the user.  In concept, this
  324. rectangle is pasted on the page left to right, top to bottom like
  325. floor tiles (Fig. B).  Again, the bounding boxes are not visible.  The
  326. only portion of this tiled pattern that is visible is the part that
  327. overlaps the object (Fig. C) being filled.  The object's path is
  328. called a clipping path, as it ``clips'' its shape from the tiled
  329. pattern (Fig. D).  Note that the fill is only masked on top of
  330. underlying objects, so any ``holes'' in the pattern will act as a
  331. window, leaving visible underlying objects.
  332.  
  333.  
  334. LAYR (0x4C415952)       /* Define a layer */
  335.  
  336. A DR2D project is broken up into one or more layers.  Each DR2D object
  337. is in one of these layers.  Layers provide several useful features.
  338. Any particular layer can be ``turned off'', so that the objects in the
  339. layer are not displayed.  This eliminates the unnecessary display of
  340. objects not currently needed on the screen.  Also, the user can lock a
  341. layer to protect the layer's objects from accidental changes.
  342.     
  343.     struct LAYRstruct {
  344.         ULONG    ID;
  345.         ULONG    Size;
  346.         USHORT   LayerID;           /* ID of the layer */
  347.         char     LayerName[16];       /* Null terminated and padded */
  348.         UBYTE    Flags;           /* Flags, from LF_*, below */
  349.         UBYTE    Pad0;           /* Always 0 */
  350.     };    
  351.  
  352. LayerID is the number assigned to this layer.  As the field's name
  353. indicates, LayerName[] is the NULL terminated name of the layer.
  354. Flags is a bit field who's bits are set according to the #defines
  355. below:
  356.  
  357.     #define LF_ACTIVE         0x01      /* Active for editing */
  358.     #define LF_DISPLAYED      0x02      /* Displayed on the screen */
  359.  
  360. If the LF_ACTIVE bit is set, this layer is unlocked.  A set
  361. LF_DISPLAYED bit indicates that this layer is currently visible on the
  362. screen.  A cleared LF_DISPLAYED bit implies that LF_ACTIVE is not set.
  363. The reason for this is to keep the user from accidentally editing
  364. layers that are invisible.
  365.  
  366.  
  367. The Object Attribute Chunks
  368.  
  369.  
  370. ATTR (0x41545452)       /* Object attributes */
  371.  
  372. The ATTR chunk sets various attributes for the objects that follow it.
  373. The attributes stay in effect until the next ATTR changes the
  374. attributes, or the enclosing FORM ends, whichever comes first.
  375.  
  376.  
  377.     /* Various fill types */
  378.     #define FT_NONE        0    /* No fill            */
  379.     #define FT_COLOR        1    /* Fill with color from palette */
  380.     #define FT_OBJECTS    2    /* Fill with tiled objects    */
  381.  
  382.     
  383.     struct ATTRstruct {
  384.         ULONG    ID;
  385.         ULONG    Size;
  386.         UBYTE    FillType;    /* One of FT_*, above    */
  387.         UBYTE    JoinType;    /* One of JT_*, below    */
  388.         UBYTE    DashPattern; /* ID of edge dash pattern */
  389.         UBYTE    ArrowHead;   /* ID of arrowhead to use  */
  390.         USHORT    FillValue;   /* Color or object with which to fill */
  391.         USHORT    EdgeValue;   /* Edge color index    */
  392.         USHORT    WhichLayer;  /* ID of layer it's in    */
  393.         IEEE    EdgeThick;   /* Line width        */
  394.     };
  395.  
  396.  
  397.  
  398. FillType specifies what kind of fill to use on this ATTR chunk's
  399. objects.  A value of FT_NONE means that this ATTR chunk's objects are
  400. not filled.  FT_COLOR indicates that the objects should be filled in
  401. with a color.  That color's ID (from the CMAP chunk) is stored in the
  402. FillValue field.  If FillType is equal to FT_OBJECTS, FillValue
  403. contains the ID of a fill pattern defined in a FILL chunk.
  404.  
  405. JoinType determines which style of line join to use when connecting
  406. the edges of line segments.  The field contains one of these four
  407. values:
  408.  
  409.     /* Join types */
  410.     #define JT_NONE       0        /* Don't do line joins */
  411.     #define JT_MITER      1        /* Mitered join */
  412.     #define JT_BEVEL      2        /* Beveled join */
  413.     #define JT_ROUND      3        /* Round join */
  414.  
  415. DashPattern and ArrowHead contain the ID of the dash pattern and arrow
  416. head for this ATTR's objects.  A DashPattern of zero means that there
  417. is no dash pattern so lines will be invisible.  If ArrowHead is 0,
  418. OPLYs have no arrow head.  EdgeValue is the color of the line
  419. segments.  WhichLayer contains the ID of the layer this ATTR's objects
  420. are in.  EdgeThick is the width of this ATTR's line segments.
  421.  
  422.  
  423.  
  424.  
  425. BBOX (0x42424F48)       /* Bounding box of next object in FORM */
  426.  
  427.  
  428. The BBOX chunk supplies the dimensions and position of a bounding box
  429. surrounding the DR2D object that follows this chunk in the FORM.  A
  430. BBOX chunk can apply to a FILL or AROW as well as a DR2D object.  The
  431. BBOX chunk appears just before its DR2D object, FILL, or AROW chunk.
  432.  
  433.     struct BBOXstruct {
  434.         ULONG    ID;
  435.         ULONG    Size;
  436.         IEEE        XMin, YMin,      /* Bounding box of obj. */
  437.                 XMax, YMax;      /* including line width    */
  438.     };
  439.  
  440. In a Cartesian coordinate system, the point (XMin, YMin) is the
  441. coordinate of the lower left hand corner of the bounding box and
  442. (XMax, YMax) is the upper right.  These coordinates take into
  443. consideration the width of the lines making up the bounding box.
  444.  
  445.  
  446. XTRN (0x5854524E)       /* Externally controlled object */
  447.  
  448.  
  449. The XTRN chunk was created primarily to allow ProVector to link DR2D
  450. objects to ARexx functions. 
  451.  
  452.     struct XTRNstruct {
  453.         ULONG   ID;
  454.         ULONG   Size;
  455.         short   ApplCallBacks;             /* From #defines, below */
  456.         short   ApplNameLength;
  457.         char    ApplName[ApplNameLength];  /* Name of ARexx func to call */
  458.     };
  459.  
  460. ApplName[] contains the name of the ARexx script ProVector calls when
  461. the user manipulates the object in some way.  The ApplCallBacks field
  462. specifies the particular action that triggers calling the ARexx script
  463. according to the #defines listed below.
  464.  
  465.     /* Flags for ARexx script callbacks */
  466.     #define    X_CLONE     0x0001    /* The object has been cloned */
  467.     #define    X_MOVE      0x0002    /* The object has been moved */
  468.     #define    X_ROTATE    0x0004    /* The object has been rotated */
  469.     #define    X_RESIZE    0x0008    /* The object has been resized */
  470.     #define    X_CHANGE    0x0010    /* An attribute (see ATTR) of the 
  471.                                         object has changed */
  472.     #define    X_DELETE    0x0020    /* The object has been deleted */
  473.     #define    X_CUT       0x0040    /* The object has been deleted, but
  474.                                         stored in the clipboard */
  475.     #define    X_COPY      0x0080    /* The object has been copied to the
  476.                                         clipboard */
  477.     #define    X_UNGROUP   0x0100    /* The object has been ungrouped */
  478.  
  479.  
  480.  
  481.  
  482.  
  483. For example, given the XTRN object:
  484.  
  485.     FORM xxxx DR2D {
  486.         XTRN xxxx { X_RESIZE | X_MOVE, 10, "Dimension" }
  487.         ATTR xxxx { 0, 0, 1, 0, 0, 0, 0.0 }
  488.         FORM xxxx DR2D {
  489.             GRUP xxxx { 2 }
  490.             STXT xxxx { 0, 0.5, 1.0, 6.0, 5.0, 0.0, 4, "3.0" }
  491.             OPLY xxxx { 2, { 5.5, 5.5, 8.5, 5.5 } }
  492.         }
  493.     }
  494.  
  495. ProVector would call the ARexx script named Dimension if the user
  496. resized or moved this object.  What exactly ProVector sends depends
  497. upon what the user does to the object.  The following list shows what
  498. string(s) ProVector sends according to which flag(s) are set.  The
  499. parameters are described below.
  500.  
  501.     X_CLONE     ``appl CLONE objID dx dy''
  502.     X_MOVE      ``appl MOVE objID dx dy''
  503.     X_ROTATE    ``appl ROTATE objID cx cy angle''
  504.     X_RESIZE    ``appl RESIZE objID cx cy sx sy''
  505.     X_CHANGE    ``appl CHANGE objID et ev ft fv ew jt fn''
  506.     X_DELETE    ``appl DELETE objID''
  507.     X_CUT       ``appl CUT objID''
  508.     X_COPY      ``appl COPY objID''
  509.     X_UNGROUP   ``appl UNGROUP objID''
  510.  
  511. where:
  512.     appl is the name of the ARexx script
  513.     CLONE, MOVE, ROTATE, RESIZE, etc. are literal strings
  514.     objID is the object ID that ProVector assigns to this object
  515.     (dx, dy) is the position offset of the CLONE or MOVE
  516.     (cx, cy) is the point around which the object is rotated or resized
  517.     angle is the angle (in degrees) the object is rotated
  518.     sx and sy are the scaling factors in the horizontal and
  519.       vertical directions, respectively. 
  520.     et is the edge type (the dash pattern index)
  521.     ev is the edge value (the edge color index)
  522.     ft is the fill type
  523.     fv is the fill index
  524.     ew is the edge weight
  525.     jt is the join type
  526.     fn is the font name
  527.  
  528. The X_CHANGE message reflects changes to the attributes found in the
  529. ATTR chunk. 
  530.  
  531. If the user resized the XTRN object shown above by factor of 2,
  532. ProVector would call the ARexx script Dimension like this: 
  533.  
  534.     Dimension RESIZE 1985427 7.0 4.75 2.0 2.0
  535.  
  536.  
  537.  
  538. The Object Chunks
  539.  
  540.  
  541. The following chunks define the objects available in the DR2D FORM.
  542.  
  543.  
  544. VBM  (0x56424D20)       /* Virtual BitMap */
  545.  
  546. The VBM chunk contains the position, dimensions, and file name of an
  547. ILBM image. 
  548.  
  549.  
  550. struct VBMstruct {
  551.     IEEE    XPos, YPos,       /* Virtual coords */
  552.         XSize, YSize,     /* Virtual size */
  553.         Rotation;       /* in degrees */
  554.     USHORT    PathLen;        /* Length of dir path */
  555.     char    Path[PathLen];  /* Null-terminated path of file */
  556. };
  557.  
  558.  
  559. The coordinate (XPos, YPos) is the position of the upper left hand
  560. corner of the bitmap and the XSize and YSize fields supply the x and y
  561. dimensions to which the image should be scaled.  Rotation tells how
  562. many degrees to rotate the ILBM around its upper left hand corner.
  563. ProVector does not currently support rotation of bitmaps and will
  564. ignore this value.  Path contains the name of the ILBM file and may
  565. also contain a partial or full path to the file.  DR2D readers should
  566. not assume the path is correct.  The full path to an ILBM on one
  567. system may not match the path to the same ILBM on another system.  If
  568. a DR2D reader cannot locate an ILBM file based on the full path name
  569. or the file name itself (looking in the current directory), it should
  570. ask the user where to find the image.
  571.  
  572.  
  573.  
  574. CPLY (0x43504C59)       /* Closed polygon */
  575. OPLY (0x4F504C59)       /* Open polygon */
  576.  
  577. Polygons are the basic components of almost all 2D objects in the DR2D
  578. FORM.  Lines, squares, circles, and arcs are all examples of DR2D
  579. polygons.  There are two types of DR2D polygons, the open polygon
  580. (OPLY) and the closed polygon (CPLY).  The difference between a closed
  581. and open polygon is that the computer adds a line segment connecting
  582. the endpoints of a closed polygon so that it is a continuous path.  An
  583. open polygon's endpoints do not have to meet, like the endpoints of a
  584. line segment.
  585.  
  586.     struct POLYstruct {
  587.         ULONG    ID;
  588.         ULONG    Size;
  589.         USHORT    NumPoints;
  590.         IEEE    PolyPoints[2*NumPoints];
  591.     };
  592.  
  593. The NumPoints field contains the number of points in the polygon and
  594. the PolyPoints array contains the (X, Y) coordinates of the points of
  595. the non-curved parts of polygons.  The even index elements are X
  596. coordinates and the odd index elements are Y coordinates.
  597.  
  598. [Figure 3 - Bezier curves]
  599.  
  600. DR2D uses Bezier cubic sections, or cubic splines, to describe curves
  601. in polygons.  A set of four coordinates (P1 through P4) defines the
  602. shape of a cubic spline.  The first coordinate (P1) is the point where
  603. the curve begins.  The line from the first to the second coordinate
  604. (P1 to P2) is tangent to the curve at the first point.  The line from
  605. P3 to P4 is tangent to the cubic section, where it ends at P4.
  606.  
  607. The coordinates describing the cubic section are stored in the
  608. PolyPoints[] array with the coordinates of the normal points.  DR2D
  609. inserts an indicator point before a set of cubic section points to
  610. differentiate a normal point from the points that describe a curve.
  611. An indicator point has an X value of 0xFFFFFFFF.  The indicator
  612. point's Y value is a bit field.  If this bit field's low-order bit is
  613. set, the points that follow the indicator point make up a cubic
  614. section.
  615.  
  616. The second lowest order bit in the indicator point's bit field is the
  617. MOVETO flag.  If this bit is set, the point (or set of cubic section
  618. points) starts a new polygon, or subpolygon.  This subpolygon will
  619. appear to be completely separate from other polygons but there is an
  620. important connection between a polygon and its subpolygon.
  621. Subpolygons make it possible to create holes in polygons.  An example
  622. of a polygon with a hole is the letter ``O''.  The ``O'' is a filled
  623. circular polygon with a smaller circular polygon within it.  The
  624. reason the inner polygon isn't covered up when the outer polygon is
  625. filled is that DR2D fills are done using the even-odd rule.
  626.  
  627. The even-odd rule determines if a point is ``inside'' a polygon by
  628. drawing a ray outward from that point and counting the number of path
  629. segments the ray crosses.  If the number is even, the point is outside
  630. the object and shouldn't be filled.  Conversely, an odd number of
  631. crossings means the point is inside and should be filled.  DR2D only
  632. applies the even-odd rule to a polygon and its subpolygons, so no
  633. other objects are considered in the calculations.
  634.  
  635. Taliesin, Inc. supplied the following algorithm to illustrate the
  636. format of DR2D polygons.  OPLYs, CPLYs, AROWs, and ProVector's outline
  637. fonts all use the same format:
  638.  
  639.  
  640.         typedef union {
  641.             IEEE num;
  642.             LONG bits;
  643.         } Coord;
  644.  
  645.         #define INDICATOR       0xFFFFFFFF
  646.         #define IND_SPLINE      0x00000001
  647.         #define IND_MOVETO      0x00000002
  648.  
  649.         /* A common pitfall in attempts to support DR2D has
  650.                 been to fail to recognize the case when an
  651.                 INDICATOR point indicates the following
  652.                 coordinate to be the first point of BOTH a
  653.                 Bezier cubic and a sub-polygon, ie. the
  654.                 value of the flag = (IND_CURVE | IND_MOVETO) */
  655.  
  656.         Coord   Temp0, Temp1;
  657.         int     FirstPoint, i, Increment;
  658.  
  659.         /* Initialize the path */
  660.         NewPath();
  661.         FirstPoint = 1;
  662.  
  663.         /* Draw the path */
  664.         i = 0;
  665.         while( i < NumPoints ) {
  666.             Temp0.num = PolyPoints[2*i];    Temp1.num = PolyPoints[2*i + 1];
  667.             if( Temp0.bits == INDICATOR ) {
  668.                 /* Increment past the indicator */
  669.                 Increment = 1;
  670.                 if( Temp1.bits & IND_MOVETO ) {
  671.                     /* Close and fill, if appropriate */
  672.                     if( ID == CPLY ) {
  673.                         FillPath();
  674.                     }
  675.                     else {
  676.                         StrokePath();
  677.                     }
  678.  
  679.                     /* Set up the new path */
  680.                     NewPath();
  681.                     FirstPoint = 1;
  682.                 }
  683.                 if( Temp1.bits & IND_CURVE ) {
  684.                     /* The next 4 points are Bezier cubic control points */
  685.                     if( FirstPoint )
  686.                         MoveTo( PolyPoints[2*i + 2], PolyPoints[2*i + 3] );
  687.                     else
  688.                         LineTo( PolyPoints[2*i + 2], PolyPoints[2*i + 3] );
  689.                     CurveTo(    PolyPoints[2*i + 4], PolyPoints[2*i + 5],
  690.                                 PolyPoints[2*i + 6], PolyPoints[2*i + 7],
  691.                                 PolyPoints[2*i + 8], PolyPoints[2*i + 9] );
  692.                     FirstPoint = 0;
  693.                     /* Increment past the control points */
  694.                     Increment += 4;
  695.                 }
  696.             }
  697.             else {
  698.                 if( FirstPoint )
  699.                     MoveTo(     PolyPoints[2*i], PolyPoints[2*i + 1] );
  700.                 else
  701.                     LineTo(     PolyPoints[2*i], PolyPoints[2*i + 1] );
  702.                 FirstPoint = 0;
  703.  
  704.                 /* Increment past the last endpoint */
  705.                 Increment = 1;
  706.             }
  707.  
  708.             /* Add the increment */
  709.             i += Increment;
  710.         }
  711.  
  712.         /* Close the last path */
  713.         if( ID == CPLY ) {
  714.             FillPath();
  715.         }
  716.         else {
  717.             StrokePath();
  718.         }
  719.  
  720.  
  721.  
  722. GRUP (0x47525550)       /* Group */
  723.  
  724. The GRUP chunk combines several DR2D objects into one.  This chunk is
  725. only valid inside nested DR2D FORMs, and must be the first chunk in
  726. the FORM.
  727.  
  728.     struct GROUPstruct {
  729.         ULONG    ID;
  730.         ULONG    Size;
  731.         USHORT    NumObjs;
  732.     };
  733.  
  734. The NumObjs field contains the number of objects contained in this
  735. group.  Note that the layer of the GRUP FORM overrides the layer of
  736. objects within the GRUP.  The following example illustrates the layout
  737. of the GRUP (and FILL) chunk.
  738.  
  739.        FORM { DR2D              /* Top-level drawing... */
  740.                 DRHD { ... }    /* Confirmed by presence of DRHD chunk */
  741.                 CMAP { ... }    /* Various other things... */
  742.                 FONS { ... }
  743.                 FORM { DR2D             /* A nested form... */
  744.                         FILL { 1 }      /* Ah!  The fill-pattern table */
  745.                         CPLY { ... }    /* with only 1 object */
  746.                 }
  747.                 FORM { DR2D             /* Yet another nested form */
  748.                         GRUP { ..., 3 } /* Ah! A group of 3 objects */
  749.                         TEXT { ... }
  750.                         CPLY { ... }
  751.                         OPLY { ... }
  752.                 }
  753.                 FORM { DR2D             /* Still another nested form */
  754.                         GRUP { ..., 2 } /* A GRUP with 2 objects */
  755.                         OPLY { ... }
  756.                         TEXT { ... }
  757.                 }
  758.         }
  759.  
  760.  
  761.  
  762. STXT (0x53545854)           /* Simple text */
  763.  
  764. The STXT chunk contains a text string along with some information on
  765. how and where to render the text. 
  766.  
  767.     struct STXTstruct {
  768.         ULONG    ID;
  769.         ULONG    Size;
  770.         UBYTE    Pad0;        /* Always 0 (for future expansion) */
  771.         UBYTE    WhichFont;      /* Which font to use */
  772.         IEEE    CharW, CharH,      /* W/H of an individual char */
  773.             BaseX, BaseY,      /* Start of baseline */
  774.             Rotation;          /* Angle of text (in degrees) */
  775.         USHORT    NumChars;
  776.         char    TextChars[NumChars];
  777.     };
  778.  
  779. The text string is in the character array, TextChars[].  The ID of the
  780. font used to render the text is WhichFont.  The font's ID is set in a
  781. FONS chunk.  The starting point of the baseline of the text is (BaseX,
  782. BaseY).  This is the point around which the text is rotated.  If the
  783. Rotation field is zero (degrees), the text's baseline will originate
  784. at (BaseX, BaseY) and move to the right.  CharW and CharH are used to
  785. scale the text after rotation.  CharW is the average character width
  786. and CharH is the average character height.  The CharW/H fields are
  787. comparable to an X and Y font size.  
  788.  
  789.  
  790.  
  791. TPTH (0x54505448)         /* A text string along a path */
  792.  
  793. This chunk defines a path (polygon) and supplies a string to render
  794. along the edge of the path.
  795.  
  796.     struct TPTHstruct {
  797.         ULONG   ID;
  798.         ULONG   Size;
  799.         UBYTE   Justification;    /* see defines, below */
  800.         UBYTE   WhichFont;        /* Which font to use */
  801.         IEEE    CharW, CharH;    /* W/H of an individual char    */
  802.         USHORT  NumChars;       /* Number of chars in the string */
  803.         USHORT  NumPoints;      /* Number of points in the path */
  804.         char    TextChars[NumChars];/* PAD TO EVEN #! */
  805.         IEEE    Path[2*NumPoints];  /* The path on which the text lies */
  806.     };
  807.  
  808. WhichFont contains the ID of the font used to render the text.
  809. Justification controls how the text is justified on the line.
  810. Justification can be one of the following values:
  811.  
  812.     #define J_LEFT         0x00    /* Left justified */
  813.     #define J_RIGHT        0x01       /* Right justified */
  814.     #define J_CENTER      0x02    /* Center text */
  815.     #define J_SPREAD      0x03    /* Spread text across path */
  816.  
  817. CharW and CharH are the average width and height of the font
  818. characters and are akin to X and Y font sizes, respectively.  A
  819. negative FontH implies that the font is upsidedown.  Note that CharW
  820. must not be negative.  NumChars is the number of characters in the
  821. TextChars[] string, the string containing the text to be rendered.
  822. NumPoints is the number of points in the Path[] array.  Path[] is the
  823. path along which the text is rendered.  The path itself is not
  824. rendered.  The points of Path[] are in the same format as the points
  825. of a DR2D polygon.
  826.  
  827.  
  828.  
  829. A Simple DR2D Example
  830.  
  831. Here is a (symbolic) DR2D FORM:
  832.  
  833.     FORM { DR2D
  834.             DRHD 16 { 0.0, 0.0, 10.0, 8.0 }
  835.             CMAP  6 { 0,0,0, 255,255,255 }
  836.             FONS  9 { 1, 0, 1, 0, "Roman" } 0
  837.             DASH 12 { 1, 2, {1.0, 1.0} }
  838.             ATTR 14 { 0, 0, 1, 0, 0, 0, 0, 0.0 }
  839.             BBOX 16 { 2.0, 2.0, 8.0, 6.0 }
  840.             FORM { DR2D
  841.                   GRUP  2 { 2 }
  842.                   BBOX 16 { 3.0, 4.0, 7.0, 5.0 }
  843.                   STXT 36 { 0,1, 0.5, 1.0, 3.0, 5.0, 0.0, 12, "Hello, World" }
  844.                   BBOX 16 { 2.0, 2.0, 8.0, 6.0 }
  845.                   OPLY 42 { 5, {2.0,2.0, 8.0,2.0, 8.0,6.0, 2.0,6.0, 2.0,2.0 }
  846.             }
  847.     }
  848.  
  849.  
  850. [Figure 4 - Simple DR2D drawing]
  851.  
  852.  
  853. The OFNT FORM
  854.  
  855.  
  856. OFNT    (0x4F464E54)       /* ID of outline font file */
  857.  
  858. ProVector's outline fonts are stored in an IFF FORM called OFNT.  This
  859. IFF is a separate file from a DR2D.  DR2D's FONS chunk refers only to
  860. fonts defined in the OFNT form.
  861.  
  862.  
  863. OFHD    (0x4F464844)       /* ID of OutlineFontHeaDer */
  864.  
  865. This chunk contains some basic information on the font.
  866.  
  867.     struct OFHDstruct {
  868.         char   FontName[32];   /* Font name, null padded */
  869.         short  FontAttrs;       /* See FA_*, below */
  870.         IEEE   FontTop,       /* Typical height above baseline */
  871.            FontBot,        /* Typical descent below baseline */
  872.            FontWidth;      /* Typical width, i.e. of the letter O */
  873.     };
  874.  
  875.     #define FA_BOLD          0x0001
  876.     #define FA_OBLIQUE       0x0002
  877.     #define FA_SERIF    0x0004
  878.  
  879. The FontName field is a NULL terminated string containing the name of
  880. this font.  FontAttrs is a bit field with flags for several font
  881. attributes.  The flags, as defined above, are bold, oblique, and
  882. serif.  The unused higher order bits are reserved for later use.  The
  883. other fields describe the average dimensions of the characters in this
  884. font.  FontTop is the average height above the baseline, FontBot is
  885. the average descent below the baseline, and FontWidth is the average
  886. character width.
  887.  
  888.  
  889. KERN    (0x4B45524C)       /* Kerning pair */
  890.  
  891. The KERN chunk describes a kerning pair.  A kerning pair sets the
  892. distance between a specific pair of characters.  
  893.  
  894. struct KERNstruct {
  895.     short   Ch1, Ch2;         /* The pair to kern (allows for 16 bits...) */
  896.     IEEE    XDisplace,      /* Amount to displace -left +right */
  897.         YDisplace;      /* Amount to displace -down +up */
  898. };
  899.  
  900. The Ch1 and Ch2 fields contain the pair of characters to kern.  These
  901. characters are typically stored as ASCII codes.  Notice that OFNT
  902. stores the characters as a 16-bit value.  Normally, characters are
  903. stored as 8-bit values.  The wary programmer will be sure to cast
  904. assigns properly to avoid problems with assigning an 8-bit value to a
  905. 16-bit variable.  The remaining fields, XDisplace and YDisplace,
  906. supply the baseline shift from Ch1 to Ch2.
  907.  
  908.  
  909.  
  910.  
  911. CHDF    (0x43484446)      /* Character definition */
  912.  
  913. This chunk defines the shape of ProVector's outline fonts.  
  914.  
  915. struct CHDFstruct {
  916.     short   Ch;        /* The character we're defining (ASCII) */
  917.     short   NumPoints;  /* The number of points in the definition */
  918.     IEEE    XWidth,     /* Position for next char on baseline - X */
  919.             YWidth;    /* Position for next char on baseline - Y */
  920.  /* IEEE    Points[2*NumPoints]*/        /* The actual points */
  921. };
  922.  
  923.  
  924. #define    INDICATOR       0xFFFFFFFF       /* If X == INDICATOR, Y is an action */
  925. #define    IND_SPLINE      0x00000001       /* Next 4 pts are spline control pts */
  926. #define    IND_MOVETO      0x00000002       /* Start new subpoly */
  927. #define IND_STROKE      0x00000004       /* Stroke previous path */
  928. #define IND_FILL        0x00000008       /* Fill previous path */
  929.  
  930. Ch is the value (normally ASCII) of the character outline this chunk
  931. defines.  Like Ch1 and Ch2 in the KERN chunk, Ch is stored as a 16-bit
  932. value.  (XWidth,YWidth) is the offset to the baseline for the
  933. following character.  OFNT outlines are defined using the same method
  934. used to define DR2D's polygons (see the description of OPLY/CPLY for
  935. details).
  936.  
  937. Because the OFNT FORM does not have an ATTR chunk, it needed an
  938. alternative to make fills and strokes possible.  There are two extra
  939. bits used in font indicator points not found in polygon indicator
  940. points, the IND_STROKE and IND_FILL bits (see defines above).  These
  941. two defines describe how to render the current path when rendering
  942. fonts.
  943.  
  944. The current path remains invisible until the path is either filled
  945. and/or stroked.  When the IND_FILL bit is set, the currently defined
  946. path is filled in with the current fill pattern (as specified in the
  947. current ATTR chunk).  A set IND_STROKE bit indicates that the
  948. currently defined path itself should be rendered.  The current ATTR's
  949. chunk dictates the width of the line, as well as several other
  950. attributes of the line.  These two bits apply only to the OFNT FORM
  951. and should not be used in describing DR2D polygons.
  952.